#ifndef _TIPO_DATO_COMPUESTO_
#define _TIPO_DATO_COMPUESTO_

/*****************************************************************
 *	tipo_dato_compuesto.h
 * 
 *  Descripcion: Clase que define un tipo de dato compuesto por 
 *               muchos tipos de dato. 
 *               Esta no puede ser instanciada pero implementa
 *               metodos comunes a los tipos compuestos.
 * **************************************************************/

#include "tipo_dato.h"
#include "excep_indice_desbordado.h"
#include <vector>

class TipoDatoCompuesto : public TipoDato {

	protected:
		
		std::vector< TipoDato* > elementos; //Elementos de la coleccion
	
		bool elementos_iguales(const TipoDatoCompuesto * dato) const;
		
		bool elementos_menores (const TipoDatoCompuesto * dato) const;
		
		void copiar_elementos(TipoDatoCompuesto * dato ) const; 
	
	public:
		/*
	 	* Constructor default: Crea una coleccion vacia, recibe como param
	 	* el tipo modelo.
	 	*/
		TipoDatoCompuesto(bool obligatorio);
		
		/*
		 * Destructor: Libera la mem consumida por la coleccion.
		 */
		virtual ~TipoDatoCompuesto();
		
		//Metodos:
		
		/*
		 * Clear: Elimina todos los elementos contenidos en el dato compuesto,
		 * liberando la mem consumida por los mismos.
		 */
		void clear();
		
		/*
		 * Permite settear como obligatorio o no a un dato compuesto.
		 */
		 void set_obligatorio(bool b);
		 
		/*
		 * Esta cargado: Devuelve true si el dato esta cargado,
		 * false en caso contrario.
		 */
		virtual bool esta_cargado() const;
		 
		/*
		 * Get Codigo Tipo: Devuelve el codigo del tipo de dato en cuestion.
		 */
		virtual CodTipo get_codigo_tipo() const = 0;
	
		/* 
		 * Op de insercion: Permite asignar un valor al objeto del tipodato.
		 * Verifica que el dato pasado por param sea una coleccion igual a la actual.
		 * Si hay problemas con el casteo tira una excep.
		 */
		virtual TipoDato& operator= (const TipoDato& dato) throw (ExcepErrorTipos) = 0;
		
		/*
		 * Op de igualacion: Devuelve true si los valores de los datos son
		 * iguales, false en caso contrario.
		 * Verifica que el dato pasado por param sea una coleccion igual a la actual..
		 * Si hay problemas con el casteo tira una excep.
		 * No chequea tipos, por lo tanto, es mejor usarla sobre los hijos
		 */
		virtual bool operator== (const TipoDato& dato) const throw (ExcepErrorTipos) = 0;
		
		/*
		 * Op <: Devuelve true si el valor del dato actual es menor al del
		 * pasado por param, false en caso contrario.
		 * Verifica que el dato pasado por param sea una coleccion igual a la actual.
		 * Si hay problemas con el casteo tira una excep.
		 * No chequea tipos, por lo tanto, es mejor usarla sobre los hijos
		 */
		virtual bool operator< (const TipoDato& dato) const throw (ExcepErrorTipos) = 0;
	
		/*
		 * Add Dato: Agrega el dato pasado como param a la estructura
		 * Devuelve true si lo pudo agregar, false en caso contrario.
		 */
		virtual bool add_dato(const TipoDato & dato) = 0;
		 
		 /*
		  * Quitar dato: Permite quitar el dato ubicado la pos pasada como param
		  * dentro de la estructura.
		  * Devuelve true si lo pudo quitar, false en caso contrario.
		  */
		 virtual bool quitar_dato(unsigned int ind);
		  
		  /*
		   * Operador []: Devuelve el dato que se encuentra en la pos
		   * determinada por el indice pasado como param.
		   * Si el indice cae fuera del tamanio de la estructura,
		   * arroja una excepcion.
		   */
		  virtual TipoDato& operator[] (size_t indice) throw (ExcepIndiceDesbordado);
		
		/*
		 * Clonar: Devuelve la referencia a un nuevo dato con el mismo 
		 * contenido que el actual.
		 * El nuevo objeto es creado en heap y debe ser liberado.
		 */
		virtual TipoDato* clonar() const = 0;
		
		/*
		 * get_tamanio: Devuelve la cantidad de campos del tipo.
		 */
		virtual unsigned int get_tamanio() const = 0;
		
		/*
		 * ToStream: Dado un stream de salida, pasa la representacion del dato
		 * al mismo.
		 */
		virtual ostream& toStream(ostream& out) const = 0;
		
		/*
		 * Crea una cadena que contiene el dato serializado. La devuelve
		 * en retorno y asigna el tamano de la misma en tam
		 */ 
		virtual void serializar(char ** retorno, unsigned int &tam) = 0;
		
		/*
		 * Obtiene un tipo de dato a partir de los datos serializados.
		 * Debe recibir el tamano de tamano de la cadena de serializados.
		 * Devuelve true si pudo realizar bien la operacion, false en
		 * caso contrario
		 */ 
		virtual bool deserializar(char * serializados, unsigned int tam) = 0;
		
};


#endif
